import os
import json
import sqlite3
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse, parse_qs
from datetime import datetime

# 数据库文件路径
DB_FILE = "micro_app.db"

class MicroServer(BaseHTTPRequestHandler):
    """微型 Web 服务器处理类"""
    
    # 初始化数据库连接（每个请求共享）
    conn = sqlite3.connect(DB_FILE, check_same_thread=False)
    cursor = conn.cursor()
    
    # 创建数据库表
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS todos (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            title TEXT NOT NULL,
            completed BOOLEAN NOT NULL DEFAULT 0,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    ''')
    conn.commit()
    
    def do_GET(self):
        """处理 GET 请求"""
        parsed_path = urlparse(self.path)
        path = parsed_path.path
        
        # 前端路由
        if path == "/":
            self.serve_file("index.html")
        elif path == "/app.js":
            self.serve_file("app.js", "text/javascript")
        elif path == "/style.css":
            self.serve_file("style.css", "text/css")
        elif path == "/favicon.ico":
            self.serve_file("favicon.ico", "image/x-icon")
        
        # API 路由
        elif path == "/api/todos":
            self.get_todos()
        elif path.startswith("/api/todo/"):
            todo_id = path.split("/")[-1]
            self.get_todo(todo_id)
        
        # 其他静态文件
        elif os.path.exists(f"./static{path}"):
            self.serve_file(f"static{path}")
        else:
            self.send_error(404, "File Not Found")
    
    def do_POST(self):
        """处理 POST 请求"""
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)
        
        if self.path == "/api/todos":
            self.create_todo(post_data)
        else:
            self.send_error(404, "Endpoint Not Found")
    
    def do_PUT(self):
        """处理 PUT 请求"""
        content_length = int(self.headers['Content-Length'])
        put_data = self.rfile.read(content_length)
        
        if self.path.startswith("/api/todo/"):
            todo_id = self.path.split("/")[-1]
            self.update_todo(todo_id, put_data)
        else:
            self.send_error(404, "Endpoint Not Found")
    
    def do_DELETE(self):
        """处理 DELETE 请求"""
        if self.path.startswith("/api/todo/"):
            todo_id = self.path.split("/")[-1]
            self.delete_todo(todo_id)
        else:
            self.send_error(404, "Endpoint Not Found")
    
    def serve_file(self, filename, content_type="text/html"):
        """提供静态文件服务"""
        try:
            with open(filename, 'rb') as file:
                self.send_response(200)
                self.send_header('Content-type', content_type)
                self.end_headers()
                self.wfile.write(file.read())
        except FileNotFoundError:
            self.send_error(404, "File Not Found")
    
    def get_todos(self):
        """获取所有待办事项"""
        self.cursor.execute("SELECT * FROM todos ORDER BY created_at DESC")
        todos = self.cursor.fetchall()
        
        # 转换为字典列表
        todos_list = []
        for todo in todos:
            todos_list.append({
                "id": todo[0],
                "title": todo[1],
                "completed": bool(todo[2]),
                "created_at": todo[3]
            })
        
        self.send_json(todos_list)
    
    def get_todo(self, todo_id):
        """获取单个待办事项"""
        self.cursor.execute("SELECT * FROM todos WHERE id = ?", (todo_id,))
        todo = self.cursor.fetchone()
        
        if todo:
            self.send_json({
                "id": todo[0],
                "title": todo[1],
                "completed": bool(todo[2]),
                "created_at": todo[3]
            })
        else:
            self.send_error(404, "Todo not found")
    
    def create_todo(self, post_data):
        """创建新的待办事项"""
        try:
            data = json.loads(post_data)
            title = data.get('title')
            
            if not title:
                self.send_error(400, "Title is required")
                return
            
            self.cursor.execute(
                "INSERT INTO todos (title) VALUES (?)",
                (title,)
            )
            self.conn.commit()
            
            # 返回新创建的待办事项
            new_id = self.cursor.lastrowid
            self.cursor.execute("SELECT * FROM todos WHERE id = ?", (new_id,))
            new_todo = self.cursor.fetchone()
            
            self.send_response(201)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            self.wfile.write(json.dumps({
                "id": new_todo[0],
                "title": new_todo[1],
                "completed": bool(new_todo[2]),
                "created_at": new_todo[3]
            }).encode('utf-8'))
            
        except json.JSONDecodeError:
            self.send_error(400, "Invalid JSON")
    
    def update_todo(self, todo_id, put_data):
        """更新待办事项"""
        try:
            data = json.loads(put_data)
            title = data.get('title')
            completed = data.get('completed')
            
            # 检查待办事项是否存在
            self.cursor.execute("SELECT * FROM todos WHERE id = ?", (todo_id,))
            if not self.cursor.fetchone():
                self.send_error(404, "Todo not found")
                return
            
            # 构建更新语句
            update_fields = []
            params = []
            
            if title is not None:
                update_fields.append("title = ?")
                params.append(title)
            
            if completed is not None:
                update_fields.append("completed = ?")
                params.append(1 if completed else 0)
            
            if not update_fields:
                self.send_error(400, "No fields to update")
                return
            
            update_query = f"UPDATE todos SET {', '.join(update_fields)} WHERE id = ?"
            params.append(todo_id)
            
            self.cursor.execute(update_query, tuple(params))
            self.conn.commit()
            
            # 返回更新后的待办事项
            self.cursor.execute("SELECT * FROM todos WHERE id = ?", (todo_id,))
            updated_todo = self.cursor.fetchone()
            
            self.send_json({
                "id": updated_todo[0],
                "title": updated_todo[1],
                "completed": bool(updated_todo[2]),
                "created_at": updated_todo[3]
            })
            
        except json.JSONDecodeError:
            self.send_error(400, "Invalid JSON")
    
    def delete_todo(self, todo_id):
        """删除待办事项"""
        # 检查待办事项是否存在
        self.cursor.execute("SELECT * FROM todos WHERE id = ?", (todo_id,))
        if not self.cursor.fetchone():
            self.send_error(404, "Todo not found")
            return
        
        self.cursor.execute("DELETE FROM todos WHERE id = ?", (todo_id,))
        self.conn.commit()
        
        self.send_response(204)
        self.end_headers()
    
    def send_json(self, data):
        """发送JSON响应"""
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps(data).encode('utf-8'))
    
    def log_message(self, format, *args):
        """自定义日志格式，减少控制台输出"""
        # 可以取消注释以下行以启用日志
        # pass
        # 或者使用更简洁的格式
        # print(f"{self.address_string()} - {format % args}")

def create_static_files():
    """创建必要的静态文件"""
    # 创建静态文件夹
    os.makedirs("static", exist_ok=True)
    
    # 创建 index.html
    with open("index.html", "w", encoding="utf-8") as f:
        f.write('''<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>微型待办事项应用</title>
    <link rel="stylesheet" href="style.css">
    <link rel="icon" href="favicon.ico" type="image/x-icon">
</head>
<body>
    <div class="container">
        <h1>我的待办事项</h1>
        
        <div class="todo-form">
            <input type="text" id="new-todo" placeholder="添加新任务...">
            <button id="add-btn">添加</button>
        </div>
        
        <ul id="todo-list"></ul>
    </div>
    
    <script src="app.js"></script>
</body>
</html>''')
    
    # 创建 style.css
    with open("style.css", "w", encoding="utf-8") as f:
        f.write('''body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: #f5f5f5;
    margin: 0;
    padding: 20px;
    color: #333;
}

.container {
    max-width: 600px;
    margin: 0 auto;
    background: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

h1 {
    text-align: center;
    color: #2c3e50;
}

.todo-form {
    display: flex;
    margin-bottom: 20px;
}

#new-todo {
    flex: 1;
    padding: 10px;
    font-size: 16px;
    border: 1px solid #ddd;
    border-radius: 4px 0 0 4px;
}

#add-btn {
    padding: 10px 20px;
    background: #3498db;
    color: white;
    border: none;
    border-radius: 0 4px 4px 0;
    cursor: pointer;
    font-size: 16px;
}

#add-btn:hover {
    background: #2980b9;
}

#todo-list {
    list-style: none;
    padding: 0;
}

.todo-item {
    display: flex;
    align-items: center;
    padding: 10px;
    border-bottom: 1px solid #eee;
}

.todo-item:last-child {
    border-bottom: none;
}

.todo-title {
    flex: 1;
    margin-left: 10px;
}

.completed .todo-title {
    text-decoration: line-through;
    color: #95a5a6;
}

.delete-btn {
    background: #e74c3c;
    color: white;
    border: none;
    border-radius: 4px;
    padding: 5px 10px;
    cursor: pointer;
}

.delete-btn:hover {
    background: #c0392b;
}''')
    
    # 创建 app.js
    with open("app.js", "w", encoding="utf-8") as f:
        f.write('''document.addEventListener('DOMContentLoaded', () => {
    const todoInput = document.getElementById('new-todo');
    const addButton = document.getElementById('add-btn');
    const todoList = document.getElementById('todo-list');
    
    // 加载待办事项
    loadTodos();
    
    // 添加待办事项
    addButton.addEventListener('click', addTodo);
    todoInput.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') addTodo();
    });
    
    function loadTodos() {
        fetch('/api/todos')
            .then(response => response.json())
            .then(todos => {
                todoList.innerHTML = '';
                todos.forEach(todo => {
                    addTodoToDOM(todo);
                });
            });
    }
    
    function addTodo() {
        const title = todoInput.value.trim();
        if (!title) return;
        
        fetch('/api/todos', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ title })
        })
        .then(response => response.json())
        .then(newTodo => {
            addTodoToDOM(newTodo);
            todoInput.value = '';
        });
    }
    
    function addTodoToDOM(todo) {
        const li = document.createElement('li');
        li.className = 'todo-item';
        li.dataset.id = todo.id;
        
        if (todo.completed) {
            li.classList.add('completed');
        }
        
        li.innerHTML = `
            <input type="checkbox" ${todo.completed ? 'checked' : ''}>
            <span class="todo-title">${todo.title}</span>
            <button class="delete-btn">删除</button>
        `;
        
        // 切换完成状态
        const checkbox = li.querySelector('input[type="checkbox"]');
        checkbox.addEventListener('change', () => {
            updateTodoStatus(todo.id, checkbox.checked);
        });
        
        // 删除待办事项
        const deleteBtn = li.querySelector('.delete-btn');
        deleteBtn.addEventListener('click', () => {
            deleteTodo(todo.id);
        });
        
        todoList.appendChild(li);
    }
    
    function updateTodoStatus(id, completed) {
        fetch(`/api/todo/${id}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ completed })
        })
        .then(response => response.json())
        .then(updatedTodo => {
            const li = document.querySelector(`.todo-item[data-id="${id}"]`);
            if (updatedTodo.completed) {
                li.classList.add('completed');
            } else {
                li.classList.remove('completed');
            }
        });
    }
    
    function deleteTodo(id) {
        fetch(`/api/todo/${id}`, {
            method: 'DELETE'
        })
        .then(() => {
            const li = document.querySelector(`.todo-item[data-id="${id}"]`);
            li.remove();
        });
    }
});''')
    

# 创建 favicon.ico（简单版本）
with open("favicon.ico", "wb") as f:
    # 这是一个最小的ICO文件（16x16像素）
    f.write(b'\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x08\x00h\x05\x00\x00\x16\x00\x00\x00('
            b'\x00\x00\x00\x10\x00\x00\x00 \x00\x00\x00\x01\x00\x08\x00\x00\x00\x00\x00@\x04\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00'
            b'\x00\x80\x00\x00\x00\x80\x80\x00\x80\x00\x00\x00\x80\x00\x80\x00\x80\x80\x00\x00\x80\x80'
            b'\x80\x00\xC0\xC0\xC0\x00\x00\x00\xFF\x00\x00\xFF\x00\x00\x00\xFF\xFF\x00\xFF\x00\x00\x00'
            b'\xFF\x00\xFF\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') # 
    
def run_server():
    create_static_files()  # 创建静态文件
    server_address = ('', 8000)
    httpd = HTTPServer(server_address, MicroServer)
    print(f"服务器运行在 http://localhost:{server_address[1]}")
    httpd.serve_forever()

if __name__ == '__main__':
    run_server()